#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, os
import difflib
from datetime import datetime
import shutil

from loguru import logger

from config import db

from models.data_model import Person, person_schema, people_schema
from models.data_model import Probe, probe_schema, probes_schema
from models.data_model import Subject, subject_schema, subjects_schema
from models.data_model import Experiment, experiment_schema, experiments_schema
from models.data_model import Acquisition, acquisition_schema, acquisitions_schema

# manage the acquisition data
class AcquisitionDataManage(object):
    def __init__(self):
        super().__init__()

        self.query_records = []
        self.acq_id_list = []
        self.pageinex = 0
        self.countperpage = 10

    def updateAllAcquisitionRecords(self):
        #acq_all = Acquisition.query.all()
        acq_all = Acquisition.query.order_by(Acquisition.timestamp.desc()).all()
        if len(acq_all) == len(self.query_records):
            return self.query_records

        for acq in acq_all:
            if acq.id not in self.acq_id_list:
                experiment = Experiment.query.filter(Experiment.id == acq.experiment_id).one_or_none()
                one_result = (acq.id, experiment.person_name, experiment.timestamp, experiment.subject_name, experiment.probe_name, acq.acquisition_method, acq.laser_wavelength, acq.laser_energy, experiment.remark)
                self.query_records.append(one_result)
                self.acq_id_list.append(acq.id)
        
        return self.query_records

    def getProbeInfo(self, probe_name):
        probe = Probe.query.filter(Probe.name == probe_name).one_or_none()
        if probe is None:
            logger.warning("Probe with name:{0} does not exist.", probe_name)
            return None
        
        return probe

    def fuzzyQuery(self, person_name_like, date_like, subject_name_like):

        fuzzy_query_result = []
        for record in self.query_records:
            fuzzy_query_result.append(record)

        if person_name_like.strip() != "":
            for record in fuzzy_query_result:
                result = difflib.SequenceMatcher(None, person_name_like, record[1])
                if result.quick_ratio() < 0.7:
                    fuzzy_query_result.remove(record)
        
        if date_like.strip() != "":
            for record in fuzzy_query_result:
                result = difflib.SequenceMatcher(None, date_like, record[2])
                if result.quick_ratio() < 0.7:
                    fuzzy_query_result.remove(record)
        
        if subject_name_like.strip() != "":
            for record in fuzzy_query_result:
                result = difflib.SequenceMatcher(None, subject_name_like, record[3])
                if result.quick_ratio() < 0.7:
                    fuzzy_query_result.remove(record)
        
        return fuzzy_query_result
    
    def getExperimentInfo(self, acquisition_id):
        logger.debug("start getExperimentInfo. input parameter: acquisition_id - {0}.", acquisition_id)

        acquisition = Acquisition.query.get(acquisition_id)
        if not acquisition:
            logger.warning("Acquisition with id:{0} does not exist.", acquisition_id)
            return None
        experiment_id = acquisition.experiment_id
        experiment = Experiment.query.get(experiment_id)
        if not experiment:
            logger.warning("Experiment with id:{0} does not exist.", experiment_id)
            return None
        
        return experiment

    def getAcquisitionInfo(self, experiment_id):
        logger.debug("start getAcquisitionInfo. input parameter: experiment_id - {0}.", experiment_id)

        acq_list = Acquisition.query.filter(Acquisition.experiment_id == experiment_id).all()
        if not acq_list:
            logger.warning("There is no acquisition in Experiment with id:{0} .", experiment_id)
            return None
        
        return acq_list

    def getAcquisitionInfoByAcquisitionID(self, acquisition_id):
        logger.debug("start getAcquisitionInfoByAcquisitionID. input parameter: acquisition_id - {0}.", acquisition_id)
        acquisition = Acquisition.query.filter(Acquisition.id == acquisition_id).one_or_none()
        if not acquisition:
            logger.warning("There is no acquisition with id:{0} .", acquisition_id)
            return None
        
        return acquisition

    ## 删除一条采集相关的记录
    def deleteAcquisitionRecords(self, acquisition_id):
        logger.trace("start deleteAcquisitionRecords. input parameter: acquisition_id - {0}.", acquisition_id)

        acquisition = Acquisition.query.get(acquisition_id)
        if not acquisition:
            logger.warning("Acquisition with id:{0} does not exist.", acquisition_id)
            return False
        
        if acquisition:
            experiment_id = acquisition.experiment_id
            left_records = [x for x in self.query_records if x[0] != acquisition_id]
            self.query_records = left_records

            if os.path.exists(acquisition.acq_data_path):
                try:
                    shutil.rmtree(acquisition.acq_data_path)
                except:
                    logger.error("deleteAcquisitionRecords error happens when delete acq_data_path:{0}", acquisition.acq_data_path)
            db.session.delete(acquisition)
            db.session.commit()
            logger.debug("deleteAcquisitionRecords. delete acquisition with id {0} successfully.", acquisition_id)

        experiment = Experiment.query.get(experiment_id)
        if experiment:
            acq = Acquisition.query.filter(Acquisition.experiment_id == experiment_id).all()
            ## 删除一个acquisition后experiment下没有其他acquisition的情况
            if not acq:
                if os.path.exists(experiment.exp_data_path):
                    try:
                        shutil.rmtree(experiment.exp_data_path)
                    except:
                        logger.error("deleteAcquisitionRecords error happens when delete exp_data_path:{0}", experiment.exp_data_path)

                    db.session.delete(experiment)
                    db.session.commit()
                    logger.debug("deleteAcquisitionRecords. delete experiment with id {0} successfully.", experiment_id)
        
        logger.trace("end deleteAcquisitionRecords.")
        return True

    # 将一个采集下的所有数据copy到新的目录下
    def exportAcquisitionRecords(self, acquisition_id, target_folder_path):
        logger.debug("start exportAcquisitionRecords. input parameter: acquisition_id - {0}, target_folder_path - {1}", acquisition_id, target_folder_path)

        acquisition = Acquisition.query.get(acquisition_id)
        if not acquisition:
            logger.warning("Acquisition with id: {0} does not exist!", acquisition_id)
            return False
        
        if not os.path.exists(acquisition.acq_data_path):
            logger.warning("Acquisition with id: {0} does not have data folder.", acquisition_id)
            return False
        
        if not os.listdir(acquisition.acq_data_path):
            logger.warning("Acquisition with id: {0} does not have acquisition data.", acquisition_id)
            return False
        
        if not os.path.exists(target_folder_path):
            logger.warning("Target folder: {0} does not exist!", target_folder_path)
            return False

        try:
            acq_dir = os.path.basename(acquisition.acq_data_path)
            target_folder_path = target_folder_path + "/" + acq_dir
            shutil.copytree(acquisition.acq_data_path, target_folder_path)
        except:
            logger.error("exportAcquisitionRecords error happens when copy folder_data_path:{0}", acquisition.acq_data_path)
        
        logger.debug("end exportAcquisitionRecords. ")
        return True

if __name__ == '__main__':
    acq_data_manage = AcquisitionDataManage()
    acq_id = 1
    acq_data_manage.deleteAcquisitionRecords(acq_id)

    acq_id = 5
    acq_data_manage.exportAcquisitionRecords(acq_id, "D:/")